package com.budwk.app.sqfw.component;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrFormatter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.budwk.app.common.config.AppException;
import com.budwk.app.sqfw.bo.PdfResourceSortBO;
import com.budwk.app.sqfw.constants.DictConstants;
import com.budwk.app.sqfw.dto.HouseSurveyFormExcelParamDTO;
import com.budwk.app.sqfw.dto.ServiceRecordPdfOrExcelCollDTO;
import com.budwk.app.sqfw.enums.HouseSurveyEnum;
import com.budwk.app.sqfw.models.*;
import com.budwk.app.sqfw.services.SqfwCompleteflowService;
import com.budwk.app.sqfw.services.SqfwDownRecordlogService;
import com.budwk.app.sqfw.services.SqfwFormsummaryNewService;
import com.budwk.app.sqfw.services.SqfwServicerecordService;
import com.budwk.app.sqfw.vo.GenerateWordAndPdfUrlVO;
import com.budwk.app.sqfwDoc.bo.ExcelCreateConfig;
import com.budwk.app.sqfwV2.dto.dto.dayingRoad.DownExcelLedgerReqVo;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.services.SysDictService;
import com.budwk.app.sys.services.SysUnitService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.sys.vo.SysDictVO;
import com.budwk.app.sys.vo.UnitServiceVo;
import com.budwk.app.util.StrUtil;
import com.budwk.app.util.poiUtils.CommonFormOfficeUtils;
import com.budwk.app.util.poiUtils.HouseSurveyFormOfficeUtils;
import com.budwk.app.util.poiUtils.UrlImageInfo;
import com.budwk.app.util.poiUtils.nutzBeanUtils.NutzIocUtils;
import com.budwk.starter.common.result.Result;
import com.budwk.starter.security.utils.SecurityUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.util.cri.SqlExpressionGroup;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class CommonComponent {


    /**
     * 构建Sqfw_formSummary默认对象
     *
     * @return
     */
    public static void buildBaseSqfwFormSummary(Sqfw_formSummary sqfwFormSummary) {
        Sys_user user = getCurrentUser();
        sqfwFormSummary.setCreateDate(new Date())
                .setCreateBy(user.getId())
                .setCreateUserName(user.getUsername())
                .setCreateUserPhone(user.getMobile())
                .setUnitId(user.getUnitId())
                .setUnitName(user.getUnitName())
                .setProvince(user.getProvince())
                .setCity(user.getCity())
                .setDistrict(user.getDistrict())
                .setCounty(user.getCounty())
                .setCommunity(user.getCommunity()).setDistrict(user.getDistrict());
    }

    public static void buildBaseSqfwFormSummaryNew(Sqfw_formSummary_new sqfwFormSummary) {
        Sys_user user = getCurrentUser();
        sqfwFormSummary.setCreateDate(new Date())
                .setCreateBy(user.getId())
                .setCreateUserName(user.getUsername())
                .setCreateUserPhone(user.getMobile())
                .setUnitId(user.getUnitId())
                .setUnitName(user.getUnitName())
                .setProvince(user.getProvince())
                .setCity(user.getCity())
                .setDistrict(user.getDistrict())
                .setCounty(user.getCounty())
                .setCommunity(user.getCommunity()).setDistrict(user.getDistrict());
    }

    /**
     * （通用方法）上传文档到PDF
     *
     * @param contentMap 内容体
     * @param filePath   文件路径
     * @param formType
     * @param fileName   文件名称
     * @return 上传结果
     */
    public static GenerateWordAndPdfUrlVO uploadPDF(Map<String, Object> contentMap, String filePath, String formType, String fileName) {
        long startTime = System.currentTimeMillis();
        List<ByteArrayOutputStream> osList = Lists.newArrayList();
        // 生成pdf
        ByteArrayOutputStream docOS = CommonFormOfficeUtils.generateWordDocument(contentMap, filePath, formType, startTime);
        osList.add(docOS);
        GenerateWordAndPdfUrlVO vo = CommonFormOfficeUtils.wordToPdfAndUpload(osList, fileName, fileName);
        log.info("generatePDFAndUpload uploadPDF res: {}", JSONObject.toJSONString(vo));
        return vo;
    }

    /**
     * 讲数组参数的属性为空的转为-
     *
     * @param list 需要转换的数组
     * @return 转换后的数组
     */
    public static List<Sqfw_formSummary> formatSqfwFormSummarysNull(List<Sqfw_formSummary> list) {
        List<Sqfw_formSummary> results = new ArrayList<>(50);
        for (Sqfw_formSummary formSummary : list) {
            results.add(StrUtil.formatSummaryNullStr(formSummary));
        }
        return results;
    }

    /**
     * 记录下载日志（异步方法，不影响代码的执行结果）
     *
     * @param reqParam 请求参数：封装为json
     * @param content  内容体：封装为json
     * @param title    下载的标题
     */
    public static void insertDownRecordLog(String reqParam, String content, String title, String url, String entityId) {
        try {
            SqfwDownRecordlogService sqfwDownRecordlogService = (SqfwDownRecordlogService) NutzIocUtils.getBeanByType(SqfwDownRecordlogService.class);
            sqfwDownRecordlogService.insertRecordLog(SecurityUtil.getUserId(), reqParam, content, title, url, entityId);
        } catch (Exception e) {
            log.error("insertDownRecordLog error:  , e");
        }
    }

    /**
     * 将对象转为Map
     *
     * @param object 对象
     * @return
     */
    public static Map<String, Object> entityToMap(Object object) {
        String reqStr = JSONObject.toJSONString(object, SerializerFeature.WRITE_MAP_NULL_FEATURES, SerializerFeature.QuoteFieldNames);
        Map<String, Object> paramMap = JSON.parseObject(reqStr, Map.class);
        return paramMap;
    }

    /**
     * 入户调查台账导出公共类
     *
     * @param formSummaryList
     * @param excelType
     * @param fileNameSuffix
     * @return
     */
    public static String generateHouseSurveyFormExcelForApp(String downType, List<Sqfw_formSummary> formSummaryList, String excelType, String fileNameSuffix, String unitName, String county, String isTempData) {
        SqfwServicerecordService sqfwServicerecordService = (SqfwServicerecordService) NutzIocUtils.getBeanByType(SqfwServicerecordService.class);
        // wzy 2023-10-11 临时处理垃圾分类改为垃圾分类宣传
        String tempExcelType = excelType;
        if (tempExcelType.equals("垃圾分类")) tempExcelType = "垃圾分类宣传";
        //zhangp 2023-12-08 非下载模板时走
        if (StringUtils.isBlank(isTempData) || !"isTemplate".equals(isTempData)) {
            if (formSummaryList.size() == 0) return null;
            String sqfwId = formSummaryList.get(0).getSqfwId();
            Sqfw_servicerecord serviceRecord = sqfwServicerecordService.fetch(sqfwId);
            unitName = serviceRecord.getCompanyName();
            county = serviceRecord.getCounty();
        }

        HouseSurveyFormExcelParamDTO excelParamDTO = new HouseSurveyFormExcelParamDTO();
        if ("zip".equals(downType)) {
            excelParamDTO.setReturnWebUrlFlag(false);
        }
        excelParamDTO.setCompleteUnitName(unitName);
        excelParamDTO.setA16Type(tempExcelType);
        excelParamDTO.setFileNameSuffix(fileNameSuffix);
        excelParamDTO.setFormSummaryList(formSummaryList);
        excelParamDTO.setCounty(county);
        String[] houseSurvers = {HouseSurveyEnum.SIX_TYPES_PERSON_LEDGER.getName(), HouseSurveyEnum.SIX_KEYNOTE_TABLE_STATIS.getName(), HouseSurveyEnum.HOME_PROMOTION_LEDGER.getName()};
        Optional<String> optional = Arrays.stream(houseSurvers).filter(e -> e.equals(excelType)).findAny();
        if (optional.isPresent()) {
            //excelParamDTO.setCounty(formSummaryList.size() > 0 ? formSummaryList.get(0).getCounty() : StringUtils.EMPTY);
            // 需要查询家庭成员信息
            getHouseSurveyExcelFamilyMemberInfo(excelParamDTO);
            String url = StringUtils.EMPTY;
            // 特殊人员巡查台账
            if (HouseSurveyEnum.SIX_TYPES_PERSON_LEDGER.getName().equals(excelType)) {
                url = HouseSurveyFormOfficeUtils.createHouseSurveySixTypePeopleStandingBookExcel(excelParamDTO, isTempData);
            }
            if (HouseSurveyEnum.SIX_KEYNOTE_TABLE_STATIS.getName().equals(excelType)) {
                url = HouseSurveyFormOfficeUtils.createHouseSurveySixTypePeopleStatistic(excelParamDTO.getFileNameSuffix(), Lists.newArrayList(excelParamDTO), excelParamDTO.getReturnWebUrlFlag(), isTempData);
            }
            // 进家入户宣传台账
            if (HouseSurveyEnum.HOME_PROMOTION_LEDGER.getName().equals(excelType)) {
                url = HouseSurveyFormOfficeUtils.exportHomeToHomePromotionLedger(excelParamDTO, isTempData);
            }
            // 记录下载日志
            insertDownRecordLog(JSONObject.toJSONString(formSummaryList), JSONObject.toJSONString(Result.data(url)), "下载" + HouseSurveyEnum.HOME_PROMOTION_LEDGER.getName(), url, null);
            return url;
        }
        // 其他情况处理
        List<Sqfw_formSummary> formSummarys = Lists.newArrayList();
        for (Sqfw_formSummary formSummary : formSummaryList) {
            String a16 = formSummary.getA16();
            //zhangp 2023-12-07 空判断否则报空指针
            if (StringUtils.isBlank(a16)) {
                continue;
            }
            Set<String> a16Set = Sets.newHashSet(a16.split(","));
            if (a16Set.contains(excelType)) {
                formSummarys.add(formSummary);
            }
        }
        excelParamDTO.setFormSummaryList(formSummarys);
        try {
            String url = HouseSurveyFormOfficeUtils.createHouseSurveyExcel(excelParamDTO, isTempData);
            insertDownRecordLog(JSONObject.toJSONString(formSummaryList), JSONObject.toJSONString(Result.data(url)), "下载" + excelType, url, null);
            return url;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static void getHouseSurveyExcelFamilyMemberInfo(HouseSurveyFormExcelParamDTO excelParamDTO) {
        List<Sqfw_formSummary> formSummaryList = excelParamDTO.getFormSummaryList();

        Map<String, List<Sqfw_cenSusPaper>> cenSusPaperMap = Maps.newHashMap();
        for (Sqfw_formSummary formSummary : formSummaryList) {
            String a7 = formSummary.getA7();
            if (StringUtils.isNotBlank(a7)) {
                List<Sqfw_cenSusPaper> a7CenSusPaperList = JSONObject.parseArray(a7, Sqfw_cenSusPaper.class);

                for (Sqfw_cenSusPaper susPaper : a7CenSusPaperList) {
                    if (StringUtils.isBlank(susPaper.getId())) {
                        cenSusPaperMap.put(susPaper.getId(), Lists.newArrayList());
                        continue;    // 为了防止脏数据id为空问题
                    }
                    List<Sqfw_cenSusPaper> familyMemberList = Lists.newArrayList();
                    for (Sqfw_cenSusPaper member : a7CenSusPaperList) {
                        if (StringUtils.isBlank(member.getId())) continue;    // 为了防止脏数据id为空问题
                        if (!susPaper.getId().equals(member.getId())) familyMemberList.add(member);
                    }
                    cenSusPaperMap.put(susPaper.getId(), familyMemberList);
                }
            }
        }
        excelParamDTO.setFamilyMemberInfoMap(cenSusPaperMap);
    }

    public static Map<String, String> getDictMap(String dictCode) {
        SysDictService sysDictService = (SysDictService) NutzIocUtils.getBeanByType(SysDictService.class);
        List<SysDictVO> sysDicts = sysDictService.listDictByCode(dictCode);
        if (sysDicts.isEmpty()) {
            throw new AppException("请先配置数据字典项项!");
        }
        return sysDicts.stream().collect(Collectors.toMap(SysDictVO::getCode, SysDictVO::getName));
    }

    /**
     * 按照特殊人员类型组件字典表的id
     * @param specialMark 特殊人员类型
     * @param sysDicts 数据字典
     * @return
     */
    public static String getSpecialMarkIds(String specialMark, List<SysDictVO> sysDicts) {
        if (StringUtils.isEmpty(specialMark)) {
            return null;
        }
        List<String> specialMarkIds = new ArrayList();
        String[] specialMarks = specialMark.split("、");
        for (String mark : specialMarks) {
            String finalMark = mark.equals("正常") ? "否" : mark;
            Optional<SysDictVO> optional = sysDicts.stream().filter(e -> e.getName().equals(finalMark)).findFirst();
            optional.ifPresent(sysDict -> specialMarkIds.add(sysDict.getId()));
        }
        if (specialMarkIds.size() > 0){
            return String.join(",", specialMarkIds);
        }
        return null;
    }

    /**
     * 组装下载excel数据
     * @param reqVo
     * @return
     */
    public static List<ExcelCreateConfig> getExcelConfigList(DownExcelLedgerReqVo reqVo) {
        if (reqVo.getExcelCodes().size() == 0) {
            throw new AppException("请指定下载文件code!");
        }
        List<ExcelCreateConfig> excelConfigList = new ArrayList<>();
        for (String excelCode : reqVo.getExcelCodes()) {
            ExcelCreateConfig config = new ExcelCreateConfig();
            config.setFileIdentity(excelCode);
            if (reqVo.isAgainGenerate()) {
                config.setIsAgainGenerate(true);
            }
            if (reqVo.isDownTemplate()) {
                config.setOnlyGenerateTemplateFlag(true);
            }
            Map<String,Object> param = new HashMap<>();
            //为了兼容老版本 ，观山湖区新版app2.0有传这个值，预防其他街道也在使用这个方法，因此加了判断
            if(StringUtils.isNotBlank(reqVo.getFillStartDate())){
                param.put("fillStartDate",reqVo.getFillStartDate());
                param.put("fillEndDate",reqVo.getFillEndDate());
                param.put("shopInfoId",reqVo.getShopInfoId());
                param.put("source",reqVo.getSource());
            }
            config.setParam(param);

            excelConfigList.add(config);
        }
        if (reqVo.isDownTemplate()) {
            reqVo.setSqfwIds(Collections.emptyList());
            reqVo.setIds(Collections.emptyList());
        }
        return excelConfigList;
    }

    /**
     * pdf合并公共代码（工作流）
     */
    public static String mergeCompleteflowPDF(List<ServiceRecordPdfOrExcelCollDTO> conditionList) {
        SqfwCompleteflowService sqfwCompleteflowService = NutzIocUtils.getBean(SqfwCompleteflowService.class);
        // 查询文档数据 获取连接
        List<String> sqfwIds = conditionList.stream().map(ServiceRecordPdfOrExcelCollDTO::getSqfwId).distinct().collect(Collectors.toList());
        Criteria cri = Cnd.cri();
        SqlExpressionGroup criSql = cri.where();
        criSql.andIn(Sqfw_completeflow::getSqfwId, sqfwIds.toArray(new String[0]));
        List<PdfResourceSortBO> pdfBoList = Lists.newArrayList();
        List<Sqfw_completeflow> completeFlowList = sqfwCompleteflowService.query(cri);

        for (Sqfw_completeflow completeFlow : completeFlowList) {
            PdfResourceSortBO bo = new PdfResourceSortBO();
            bo.setSortDate(completeFlow.getCreateDate());
            bo.setSqfwId(completeFlow.getSqfwId());
            bo.setPdfPath(completeFlow.getResourcePath());
            bo.setServiceType(completeFlow.getFileType());
            pdfBoList.add(bo);
        }
        // 将这些文档按照时间先后顺序进行排序
        pdfBoList.sort(Comparator.comparing(PdfResourceSortBO::getSortDate));
        List<String> pdfPathList = pdfBoList.stream().map(PdfResourceSortBO::getPdfPath).collect(Collectors.toList());
        // 用于生成文件规则
        Set<String> serviceTypeTotalSet = conditionList.stream().map(ServiceRecordPdfOrExcelCollDTO::getServiceType).collect(Collectors.toSet());
        String fileNameTemplate = "{}文档集合{}";

        String fileNamePrefix = "工作文档";
        if (serviceTypeTotalSet.size() == 1) fileNamePrefix = serviceTypeTotalSet.iterator().next();
        String fileName = StrFormatter.format(fileNameTemplate, fileNamePrefix, DateUtil.format(new Date(), "yyyyMMddHHmmss"));
        String url = CommonFormOfficeUtils.createConvergePdfAndUpload(pdfPathList, fileName);
        // 3 记录下载日志
        // 获取iDs
        String ids = completeFlowList.stream().map(Sqfw_completeflow::getId).collect(Collectors.joining(""));
        insertDownRecordLog(JSONObject.toJSONString(conditionList), JSONObject.toJSONString(Result.data(url)), fileName, url, ids);
        return url;
    }

    public static void downFile(HttpServletResponse response, String filepath, String fileName) {
        // 设置输出的格式
        response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes(), StandardCharsets.ISO_8859_1));
        InputStream inStream = null;
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            inStream = new FileInputStream(filepath);
            // 循环取出流中的数据
            byte[] buff  = new byte[1024];
            int len;
            while ((len = inStream.read(buff )) > 0) {
                outputStream.write(buff, 0, len);
                outputStream.flush();
            }
        } catch (IOException e) {
            log.error("downloadHistroyLog error: ", e);
            throw new AppException("文件下载失败，请联系管理员!");
        } finally {
            IOUtils.closeQuietly(outputStream);
            IOUtils.closeQuietly(inStream);
        }

    }

    public static UrlImageInfo getImageUrl(String imageUrl, Float targetLength, Float targetHeight) {
        String imageSourceUrl = imageUrl; // 原始文件url
        UrlImageInfo urlImageInfo = null;
        try {
            if (imageUrl.startsWith("/"))
                imageUrl = NutzIocUtils.getOssPrefix() + imageUrl;
            // 从网络上读取图片然后得到输入流和宽高
            if (targetHeight != null) {
                urlImageInfo = new UrlImageInfo(imageUrl, targetLength, targetHeight);
            } else {
                urlImageInfo = new UrlImageInfo(imageUrl, targetLength);
            }
        } catch (Exception e) {
            if (imageSourceUrl.startsWith("/"))
                imageSourceUrl = NutzIocUtils.getOssPrefixHuaWei() + imageSourceUrl;
            // 从网络上读取图片然后得到输入流和宽高
            if (targetHeight != null) {
                urlImageInfo = new UrlImageInfo(imageSourceUrl, targetLength, targetHeight);
            } else {
                urlImageInfo = new UrlImageInfo(imageSourceUrl, targetLength);
            }

        }
        return urlImageInfo;
    }

    public static Map<String, String> getMeetRecordTypes() {
        return getDictMap(DictConstants.MEET_RECORD_TYPES);
    }

    /**
     * 获取当前用户信息
     * @return
     */
    public static Sys_user getCurrentUser() {
        SysUserService userService = NutzIocUtils.getBean(SysUserService.class);
        Sys_user user = userService.fetch(SecurityUtil.getUserId());
        if (user == null) {
            throw new AppException("用户未登陆！");
        }
        return user;
    }

    /**
     * 查询同一单位下的所有数据
     * @param sqfwId
     * @param type
     * @return
     */
    public static List<Sqfw_formSummary_new> querySummarys(String sqfwId, String type) {
        Cnd cnd = Cnd.NEW();
        SqlExpressionGroup where = cnd.where();
        if (StringUtils.isNotEmpty(sqfwId)) {
            where.andEquals(Sqfw_formSummary_new::getSqfwId, sqfwId);
        }
        where.andEquals(Sqfw_formSummary_new::getType, type)
                .andEquals(Sqfw_formSummary_new::getUnitId, SecurityUtil.getUnitId());
        cnd.getOrderBy().desc(Sqfw_formSummary_new::getFillDate);
        SqfwFormsummaryNewService sqfwFormsummaryNewService = NutzIocUtils.getBean(SqfwFormsummaryNewService.class);
        List<Sqfw_formSummary_new> list = sqfwFormsummaryNewService.query(cnd);
        return list;
    }
    public static String getEntityIds(List<Sqfw_formSummary_new> list, List<String> sqfwIds, String type) {
        if (CollectionUtil.isNotEmpty(list)) {
            return list.stream().map(Sqfw_formSummary_new::getId).collect(Collectors.joining());
        }
        if (CollectionUtil.isNotEmpty(sqfwIds)) {
            SqfwFormsummaryNewService sqfwFormsummaryNewService = NutzIocUtils.getBean(SqfwFormsummaryNewService.class);
            List<Sqfw_formSummary_new> list1 = sqfwFormsummaryNewService.queryBySqfwIdsAndType(sqfwIds, type);
            return list1.stream().map(Sqfw_formSummary_new::getId).collect(Collectors.joining());
        }
        return null;
    }

    /**
     * 判断用户是否配置模板信息
     */
    public static boolean checkUserTemplateInfo(String userId, String type, String templateDictCode) {
        SysUserService userService = NutzIocUtils.getBean(SysUserService.class);
        Sys_user user = userService.fetch(userId);
        // 查询用户单位信息
        SysUnitService unitService = NutzIocUtils.getBean(SysUnitService.class);
        Sys_unit unit = unitService.fetch(user.getUnitId());
        if (unit == null) {
            throw new AppException("该用户未配置单位，请检查单位配置！");
        }
        List<UnitServiceVo> serviceTypeTemplate = unit.getServiceTypeTemplate();
        if (serviceTypeTemplate != null) {
            Optional<UnitServiceVo> first = serviceTypeTemplate.stream().filter(e -> e.getKey().equals(type)).findFirst();
            if (first.isPresent()) {
                List<UnitServiceVo.UnitSerClass> unitSerClasses = first.get().getValue();
                Optional<UnitServiceVo.UnitSerClass> optional = unitSerClasses.stream().filter(e -> e.getPath().equals(templateDictCode)).findFirst();
                if (optional.isPresent()) {
                    return true;
                }
            }
        }
        return false;
    }
}
